package com.tbit.uqbike.webmanager.controller;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.StrUtil;
import com.tbit.common.constant.MethodEnum;
import com.tbit.common.constant.ModuleEnum;
import com.tbit.common.enums.OperaPswEnum;
import com.tbit.uqbike.annos.OperateLog;
import com.tbit.uqbike.constant.UserConstant;
import com.tbit.uqbike.enums.SystemCodeEnum;
import com.tbit.uqbike.enums.giftcard.CardType;
import com.tbit.uqbike.manager.exception.BaseException;
import com.tbit.uqbike.object.pojo.GiftCard;
import com.tbit.uqbike.object.pojo.GiftCardUser;
import com.tbit.uqbike.object.pojo.User;
import com.tbit.uqbike.object.pojo.dto.GiftCardAddDTO;
import com.tbit.uqbike.object.pojo.dto.GiftCardBatchUpdateDTO;
import com.tbit.uqbike.object.pojo.vo.*;
import com.tbit.uqbike.object.value.LoginInfo;
import com.tbit.uqbike.object.view.JsonResult;
import com.tbit.common.entity.view.Result;
import com.tbit.uqbike.service.business.*;
import com.tbit.uqbike.webmanager.util.Assert;
import com.tbit.uqbike.webmanager.util.excel.ExcelUtil;
import com.tbit.utils.DateTimeUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.constraints.NotNull;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * 礼品卡 充值配置
 *
 * @author chenmengran
 * @Description: 礼品卡
 * @date 2019\12\28 002814:46
 */
@Slf4j
@Validated
@RestController
@RequestMapping(value = "/giftCard", produces = BaseController.MEDIA_JSON_UTF8)
public class GiftCardController extends BaseController {
    @Autowired
    private GiftCardService giftCardService;
    @Autowired
    private AccountService accountService;
    @Autowired
    private GiftCardUserService giftCardUserService;
    @Resource
    private UserService userService;
    @Autowired
    private OperaPswService operaPswService;

    /**
     * 新增礼品卡
     *
     * @param dto 礼品卡信息
     */
    @PostMapping("/add")
    @OperateLog(module = ModuleEnum.ACCOUNTFEE, methods = MethodEnum.GIFTCARD_ADD)
    public JsonResult add(@RequestBody @Validated GiftCardAddDTO dto,
                                HttpServletRequest request) {
        checkParams(dto);
        if (StrUtil.isNotEmpty(dto.getRemark()) && dto.getRemark().length() > 255){
            throw new BaseException("礼品卡备注过长");
        }
        GiftCard giftCard = new GiftCard();
        BeanUtil.copyProperties(dto, giftCard, "expireDate");
        giftCard.setExpireDate(new Date(dto.getExpireDate()));
        log.info("[新增礼品卡] 礼品卡信息: {}", dto);

        // 获取用户信息
        LoginInfo loginInfo = getLogin(request);
        if (!loginInfo.type.equals(UserConstant.USER_AGENT)) {
            Assert.notNull(giftCard.getAccountId(), "ver.accountId.notNull");
        } else {
            giftCard.setAccountId(loginInfo.id);
        }

        giftCardService.addEdit(loginInfo, giftCard);

        return JsonResult.ok();
    }

    private void checkParams(GiftCardAddDTO dto) {
        if (dto.getCardType() == CardType.COUPON.code) {
            Assert.notNull(dto.getCouponId(), "ver.couponId.notNull");
            Assert.notNull(dto.getCouponCount(), "ver.couponCount.notNull");
            Assert.notNull(dto.getCouponExpireDays(), "ver.validDays.notNull");
            dto.setMoney(0);
        } else if (dto.getCardType() == CardType.GIFT_CASH.code) {
            Assert.notNull(dto.getMoney(), "ver.money.notNull");
            dto.setCouponId(null);
            dto.setCouponCount(null);
            dto.setCouponExpireDays(null);
        }
    }

    /**
     * 分页查询礼品卡
     *
     * @param accountId 区域id
     * @param sortName  排序字段
     * @param sign      排序方式 1-升序 2-降序
     * @param pageNO    页码
     * @param rowCount  每页显示条数
     * @param cardNO    卡号
     * @param phone     手机号
     * @param startTime 开始时间
     * @param endTime   结束时间
     * @param cardType  卡类型 0-礼品金 1-优惠券
     */
    @RequestMapping("/getGiftCard")
    public JsonResult getCoupon(Integer accountId, String sortName,
                                                  @RequestParam(defaultValue = "1") Integer sign,
                                                  @RequestParam(defaultValue = "1") Integer pageNO,
                                                  @RequestParam(defaultValue = "10") Integer rowCount,
                                                  String cardNO, Long startTime, Long endTime, String phone, Integer cardType,
                                                  HttpServletRequest request) {
        // 获取用户信息
        LoginInfo loginInfo = getLogin(request);
        if (!loginInfo.type.equals(UserConstant.USER_AGENT)) {
            Assert.notNull(accountId, "ver.accountId.notNull");
        } else {
            accountId = loginInfo.id;
        }
        if (sortName != null && !"".equals(sortName)) {
            sortName = sortName + (sign == 1 ? " asc" : " desc");
        }
        Integer userId = null;
        if (StringUtils.isNotBlank(phone)) {
            userId = selectUserIdByPhoneAndAreaId(accountId, phone);
        }
        List<GiftCardVO> coupons = giftCardService.queryPage(loginInfo, accountId, pageNO, rowCount, sortName, cardNO, startTime, endTime, userId, cardType);
        Integer total = giftCardService.queryCount(accountId, cardNO, startTime, endTime, userId, cardType);
        return JsonResult.ok(coupons, total);
    }

    /**
     * 导出礼品卡信息
     *
     * @param accountId 区域id
     * @param sortName  排序字段
     * @param cardNO    卡号
     * @param phone     手机号
     * @param sign      排序方式 1-升序 2-降序
     * @param startTime 开始时间
     * @param endTime   结束时间
     * @param cardType  卡类型 0-礼品金 1-优惠券
     */
    @GetMapping("/export")
    public Result<String> exportGiftCard(@NotNull(message = "ver.areaId.notNull") Integer accountId, String sortName, String cardNO, String phone,
                                         @RequestParam(defaultValue = "1") Integer sign,
                                         Long startTime, Long endTime, Integer cardType,
                                         HttpServletRequest request) {

        // 获取用户信息
        LoginInfo loginInfo = getLogin(request);
        int pageNo = 1;
        int rowCount = 20000;
        Integer userId = null;
        if (StringUtils.isNotBlank(phone)) {
            userId = selectUserIdByPhoneAndAreaId(accountId, phone);
        }
        if (giftCardService.queryCount(accountId, cardNO, startTime, endTime, userId, cardType) > rowCount){
            return Result.error("导出数据量过大");
        }
        List<GiftCardVO> giftCardList = giftCardService.queryPage(loginInfo, accountId, pageNo, rowCount, sortName, cardNO, startTime, endTime, userId, cardType);
//        else {
//            Integer userId = selectUserIdByPhoneAndAreaId(accountId, phone);
//            giftCardList = giftCardService.queryPageByPhone(loginInfo, accountId, userId, pageNo, rowCount, sortName, String.valueOf(sign), cardNO, startTime, endTime);
//            giftCardList.forEach(x -> x.setPhone(phone));
//        }
        final Date currentDate = new Date();
        List<GiftCardExportVO> cardList = giftCardList.stream().map(x -> {
            GiftCardExportVO giftCardExportVO = new GiftCardExportVO();
            giftCardExportVO.setPhone(x.getPhone());
            giftCardExportVO.setMoney(x.getMoney() / 100D);
            giftCardExportVO.setCreateTime(x.getCreateTime());
            giftCardExportVO.setExpireDate(x.getExpireDate());
            giftCardExportVO.setMemberFeeDays(x.getMemberFeeDays());
            giftCardExportVO.setCardNO(x.getCardNO());
            giftCardExportVO.setCardType(x.getCardType() == 0 ? "礼品金" : "优惠券");
            giftCardExportVO.setCouponCount(x.getCouponCount());
            giftCardExportVO.setCouponExpireDays(x.getCouponExpireDays());
            giftCardExportVO.setCouponName(x.getCouponName());
            giftCardExportVO.setCouponMoney(x.getCouponMoney() == null ? null : x.getCouponMoney() / 100);
            giftCardExportVO.setCouponTime(x.getCouponTime());

            String state = x.getState() == 1 ? "已兑换" : "未兑换";
            boolean expired = x.getExpireDate().before(currentDate);
            if (expired && x.getState() == 0) {
                state = state + "(已失效)";
            }
            giftCardExportVO.setState(state);
            giftCardExportVO.setRemark(x.getRemark());
            return giftCardExportVO;
        }).collect(Collectors.toList());
        ExcelUtil<GiftCardExportVO> excel = new ExcelUtil<>(GiftCardExportVO.class);
        JsonResult jsonResult = excel.exportExcel(cardList, "礼品卡记录");
        return Result.success(jsonResult.getData().toString());
    }

    /**
     * 礼品卡信息
     */
    @RequestMapping("/getGiftCardByPhone")
    public JsonResult getGiftCardByPhone(@NotNull(message = "ver.phone.notNull") String phone,
                                         @NotNull(message = "ver.areaId.notNull") Integer accountId,
                                         String sortName, String sign,
                                         @RequestParam(defaultValue = "10") Integer rowCount,
                                         @RequestParam(defaultValue = "1") Integer pageNO,
                                         String cardNO, Long startTime, Long endTime,
                                         HttpServletRequest request) {
        // 获取用户信息
        LoginInfo loginInfo = getLogin(request);
        Integer userId = selectUserIdByPhoneAndAreaId(accountId, phone);
        Integer total = giftCardService.selectTotalCount(accountId, userId, cardNO, startTime, endTime);
        if (total <= 0) {
            return JsonResult.ok(Collections.emptyList(), 0);
        }
        List<GiftCard> coupons = giftCardService.queryPageByPhone(loginInfo, accountId, userId, pageNO, rowCount, sortName, sign, cardNO, startTime, endTime);
        coupons.forEach(x -> x.setPhone(phone));
        return JsonResult.ok(coupons, total);
    }

    /**
     * 查询用户区域礼品卡余额
     */
    @RequestMapping("/getByUser")
    public JsonResult getByUser(Integer accountId, Integer userId, HttpServletRequest request) {
        Assert.notNull(accountId, "ver.accountId.notNull");
        Assert.notNull(accountId, "ver.userId.notNull");

        // 获取用户信息
        LoginInfo loginInfo = getLogin(request);

        GiftCardUser giftCardUser = giftCardUserService.getByUser(accountId, userId);

        return JsonResult.ok(giftCardUser);
    }

    /**
     * 礼品卡余额充值
     */
    @RequestMapping("/recharge")
    @OperateLog(module = ModuleEnum.ACCOUNTFEE, methods = MethodEnum.GIFTCARD_RECHANGE)
    public JsonResult recharge(Integer accountId, Integer userId, Integer money, String remark, String operaPsw, HttpServletRequest request) {
        Assert.notNull(accountId, "ver.accountId.notNull");
        Assert.notNull(userId, "ver.userId.notNull");
        Assert.notNull(money, "money_not_null");
        Assert.hasLength(remark, "remark_not_null");
        LoginInfo loginInfo = getLogin(request);
        // 金额不能等于0
        if (money == 0) {
            throw new BaseException("money_not_zero");
        }
        /**操作密码校验*/
        operaPswService.checkOperaPsw(loginInfo, OperaPswEnum.OPERA_PSW_MONEY_CONFIG.getModule(), operaPsw);

        giftCardUserService.recharge(accountId, userId, money, remark, loginInfo);
        return JsonResult.ok();
    }

    private final ExcelUtil<CardNoVO> excelUtil = new ExcelUtil<>(CardNoVO.class);

    /**
     * 批量新增礼品卡
     *
     * @param dto 礼品卡信息
     */
    @PostMapping("/addBatch")
    @OperateLog(module = ModuleEnum.ACCOUNTFEE, methods = MethodEnum.GIFTCARD_BATCHADD)
    public JsonResult addBatch(@RequestBody GiftCardAddDTO dto,
                         HttpServletResponse response, HttpServletRequest request) {
        Assert.notNull(dto.getCardType(), "ver.cardType.notNull");
        Assert.notNull(dto.getNum(), "ver.num.notNull");
        checkParams(dto);

        GiftCard giftCard = new GiftCard();
        BeanUtil.copyProperties(dto, giftCard, "expireDate");
        giftCard.setExpireDate(new Date(dto.getExpireDate()));

        LoginInfo loginInfo = getLogin(request);
        if (!loginInfo.type.equals(UserConstant.USER_AGENT)) {
            Assert.notNull(giftCard.getAccountId(), "ver.adAccountId.notNull");
        } else {
            giftCard.setAccountId(loginInfo.id);
        }

        List<String> list = giftCardService.addBatch(giftCard, dto.getNum());

        List<CardNoVO> cardNoVOList = list.stream().map(s -> new CardNoVO(){{ setCardNO(s); }}).collect(Collectors.toList());

        return excelUtil.exportExcel(cardNoVOList, "礼品卡" + DateTimeUtil.getNowTimeyyyyMMddHHmmss());
    }

    /**
     * 批量修改礼品卡余额
     *
     * @param giftCardBatchUpdateDTO .
     * @param request                .
     * @return .
     */
    @PostMapping("/batch/update")
    @OperateLog(module = ModuleEnum.ACCOUNTFEE, methods = MethodEnum.GIFTCARD_BATCHSEND)
    public Result<List<GiveRideCardVo>> batchUpdateGiftCard(@Validated GiftCardBatchUpdateDTO giftCardBatchUpdateDTO,
                                                            HttpServletRequest request) {
        /**操作密码校验*/
        operaPswService.checkOperaPsw(getLogin(request), OperaPswEnum.OPERA_PSW_MONEY_CONFIG.getModule(), giftCardBatchUpdateDTO.getOperaPsw());

        giftCardBatchUpdateDTO.setLoginInfo(getLogin(request));
        return giftCardService.batchSendGiftCard(giftCardBatchUpdateDTO);
    }

    private Integer selectUserIdByPhoneAndAreaId(Integer accountId, String phone) {
        Integer brandId = accountService.getBrandIdByAccountId(accountId, 3);
        return Optional.ofNullable(userService.getByAccountIdAndPhone(brandId, phone))
                .filter(CollectionUtils::isNotEmpty)
                .map(x -> x.get(0))
                .map(User::getUserId)
                .orElseThrow(() -> new BaseException(SystemCodeEnum.USER_NOT_EXIST));
    }

}
